package 系统资源类

import (
	扩展类 "gitee.com/go_888/extends/extend"
	"gitee.com/go_888/internal-call/gopsutil/process"
	"log"
	"os"
	"time"
)

// X取自进程ID 返回当前进程的ID。
// 使用该函数的原因是为了在需要标识当前进程时，提供一个统一的获取进程ID的方式。
func X取自进程ID() int {
	return int(os.Getpid())
}

// 取进程ID列表 获取系统中所有进程的ID列表
// 该函数不接受任何参数
// 返回值是一个int32类型的切片，包含所有进程的ID
// 可能返回一个错误，如果获取进程ID列表时出现任何问题
func X取进程ID列表() ([]int, error) {
	pids, err := process.Pids()
	返回 := []int{}
	for i := range pids {
		返回 = append(返回, int(pids[i]))
	}
	return 返回, err
}

// X进程ID是否存在 检查给定的进程ID是否存在于当前系统中。
// 参数:
// pid - 需要检查的进程ID。
// 返回值:
// bool - 如果进程ID存在，返回true；否则返回false。
// error - 如果在检查过程中发生错误，返回该错误信息；否则返回nil。
func X进程ID是否存在(pid int) (bool, error) {
	return process.PidExists(int32(pid))
}

// X取进程CPU占用率 获取指定进程在一定时间内的CPU占用率。
// 参数:
// pid: 需要监控的进程ID。
// 统计时长_秒: 可选参数，指定统计CPU占用率的时间间隔，单位为秒。
// 返回值:
// float64: 进程在指定时间间隔内的CPU占用率百分比。
// error: 错误信息，如果打开进程失败或获取CPU占用率过程中发生错误，则返回相应错误。
func X取进程CPU占用率(pid int, 统计时长_秒 ...int) (float64, error) {
	// 尝试根据进程ID创建一个新的Process对象
	p, err := process.NewProcess(int32(pid))
	if err != nil {
		// 如果创建Process对象失败，返回错误信息
		log.Printf("X取进程CPU占用率(),打开进程失败:" + err.Error())
		return -1, err
	}
	// 设置默认延时时间为1秒
	延时 := 1
	// 如果提供了延时参数，使用该参数的值
	if len(统计时长_秒) > 0 {
		延时 = 统计时长_秒[0]
	}

	// 返回进程在指定时间间隔内的CPU占用率
	占用率, err := p.Percent(time.Second * time.Duration(延时))
	return 扩展类.X四舍五入(占用率, 2), err
}

// X取进程创建时间戳  返回进程自纪元以来的创建时间（以UTC时间为标准，单位为毫秒）
// 该函数首先尝试创建一个Process对象，然后通过该对象获取进程的创建时间。
// 参数:
// pid - 进程ID，用于标识要获取其运行时间戳的进程。
// 返回值:
// int64 - 进程的创建时间戳,单位为毫秒
// error - 如果创建Process对象或获取创建时间失败，则返回错误。
func X取进程创建时间戳(pid int) (int64, error) {
	// 尝试根据进程ID创建一个新的Process对象。
	p, err := process.NewProcess(int32(pid))
	if err != nil {
		// 如果创建Process对象失败，则返回错误信息。
		log.Printf("X取进程创建时间戳(),打开进程失败:" + err.Error())
		return -1, err
	}
	// 返回进程的创建时间戳。
	return p.CreateTime()
}

// X取进程内存占用率 根据给定的进程ID，返回该进程的内存占用率。
// 参数:
// pid - 进程ID。
// 返回值:
// 进程的内存占用率（百分比），如果操作成功；否则返回错误信息。
func X取进程内存占用率(pid int) (float64, error) {
	// 尝试根据进程ID创建一个新的Process对象。
	p, err := process.NewProcess(int32(pid))
	if err != nil {
		// 如果创建Process对象失败，则返回错误信息。
		log.Printf("X取进程内存占用率(),打开进程失败:" + err.Error())
		return -1, err
	}
	// 获取进程的内存占用率。
	占用率, err := p.MemoryPercent()
	// 返回进程的内存占用率（四舍五入到小数点后两位），如果操作成功；否则返回错误信息。
	return 扩展类.X四舍五入(float64(占用率), 2), err
}

// X取进程父进程ID 根据指定的进程ID获取其父进程的ID。
// 参数:
// pid - 要查询的进程ID。
// 返回值:
// 父进程的ID和一个可能的错误。
func X取进程父进程ID(pid int) (int, error) {
	// 尝试根据进程ID创建一个新的Process对象。
	p, err := process.NewProcess(int32(pid))
	if err != nil {
		// 如果创建Process对象失败，则返回错误信息。
		log.Printf("X取进程父进程ID(),打开进程失败:" + err.Error())
		return -1, err
	}
	// 返回父进程的ID。
	ppid, err := p.Ppid()
	return int(ppid), err
}

// X取进程名称 根据给定的进程ID获取进程名称。
// 参数:
// pid - 需要获取名称的进程ID。
// 返回值:
// 进程名称作为字符串。
// 如果获取进程名称过程中发生错误，则返回错误信息。
func X取进程名称(pid int) (string, error) {
	// 尝试根据进程ID创建一个新的Process对象。
	p, err := process.NewProcess(int32(pid))
	if err != nil {
		// 如果创建Process对象失败，则返回错误信息。
		log.Printf("X取进程名称(),打开进程失败:" + err.Error())
		return "", err
	}

	// 返回进程名称。
	return p.Name()
}

// X取进程路径 根据给定的进程ID获取进程的执行文件路径。
// 参数:
// pid - 进程ID。
// 返回值:
// 进程的执行文件路径。
// 如果获取路径过程中发生错误，则返回空字符串和错误信息。
func X取进程路径(pid int) (string, error) {
	// 尝试根据进程ID创建一个新的Process对象。
	p, err := process.NewProcess(int32(pid))
	if err != nil {
		// 如果创建Process对象失败，则返回错误信息。
		log.Printf("X取进程路径(),打开进程失败:" + err.Error())
		return "", err
	}
	// 返回进程的执行文件路径。
	return p.Exe()
}

// X取进程启动参数 根据指定的进程ID获取进程的启动参数。
// 参数:
// pid - 进程ID。
// 返回值:
// string - 进程的启动参数。
// error - 可能发生的错误。
func X取进程启动参数(pid int) (string, error) {
	// 尝试根据进程ID创建一个新的Process对象。
	p, err := process.NewProcess(int32(pid))
	if err != nil {
		// 如果创建Process对象失败，则返回错误信息。
		log.Printf("X取进程启动参数(),打开进程失败:" + err.Error())
		return "", err
	}
	// 返回进程的启动参数。
	return p.Cmdline()
}

// X取进程启动参数数组 根据给定的进程ID，获取进程的启动参数数组。
// 参数:
// pid - 进程ID。
// 返回值:
// []string - 进程的启动参数数组。
// error - 如果获取启动参数失败，则返回错误信息。
func X取进程启动参数数组(pid int) ([]string, error) {
	// 尝试根据进程ID创建一个新的Process对象。
	p, err := process.NewProcess(int32(pid))
	if err != nil {
		// 如果创建Process对象失败，则返回错误信息。
		log.Printf("X取进程启动参数数组(),打开进程失败:" + err.Error())
		return []string{}, err
	}
	// 返回进程的启动参数。
	return p.CmdlineSlice()
}

// X取进程工作目录 根据给定的进程ID获取进程的当前工作目录。
// 参数:
// pid - 需要查询的进程ID。
// 返回值:
// 进程的当前工作目录路径。
// 如果获取目录失败，返回错误信息。
func X取进程工作目录(pid int) (string, error) {
	// 尝试根据进程ID创建一个新的Process对象。
	p, err := process.NewProcess(int32(pid))
	if err != nil {
		// 如果创建Process对象失败，则返回错误信息。
		log.Printf("X取进程工作目录(),打开进程失败:" + err.Error())
		return "", err
	}
	// 返回进程的当前工作目录。
	return p.Cwd()
}

type X进程内存信息 struct {
	X内存占用大小 uint64 `json:"rss"` // 常驻集大小，单位：字节
	X虚拟内存大小 uint64 `json:"vms"` // 虚拟内存大小，单位：字节
}

// X取进程内存信息 根据给定的进程ID，获取进程的内存使用信息。
// 参数:
// pid - 进程ID。
// 返回值:
// X进程内存信息 - 包含进程的内存占用大小和虚拟内存大小的信息。
// error - 如果获取内存信息失败，则返回错误。
func X取进程内存信息(pid int) (X进程内存信息, error) {
	// 尝试根据进程ID创建一个新的Process对象。
	p, err := process.NewProcess(int32(pid))
	if err != nil {
		// 如果创建Process对象失败，则返回错误信息。
		log.Printf("X取进程内存信息(),打开进程失败:" + err.Error())
		return X进程内存信息{}, err
	}
	// 获取进程的内存使用信息。
	内存信息, err := p.MemoryInfo()
	if err != nil {
		log.Printf("X取进程内存信息(),获取失败:" + err.Error())
		return X进程内存信息{}, err
	}
	// 返回进程的内存占用大小和虚拟内存大小。
	return X进程内存信息{
		X内存占用大小: 内存信息.RSS,
		X虚拟内存大小: 内存信息.VMS,
	}, nil
}

// X取进程子进程ID 根据给定的进程ID，获取其所有子进程的ID。
// 参数pid：要获取其子进程的父进程ID。
// 返回值[]int64：包含所有子进程ID的数组。
// 返回值error：如果获取子进程失败，则返回错误信息。
func X取进程子进程ID(pid int) ([]int, error) {
	// 尝试根据进程ID创建一个新的Process对象。
	p, err := process.NewProcess(int32(pid))
	if err != nil {
		// 如果创建Process对象失败，则返回错误信息。
		log.Printf("X取进程子进程ID(),打开进程失败:" + err.Error())
		return []int{}, err
	}

	// 获取指定进程的所有子进程。
	子进程数组, err := p.Children()
	if err != nil {
		log.Printf("X取进程子进程ID(),获取失败:" + err.Error())
		return []int{}, err
	}
	// 初始化一个数组，用于存储子进程的ID。
	返回数组 := []int{}

	// 遍历子进程数组，提取每个子进程的ID，并将其转换为int64类型后，添加到返回数组中。
	for i := range 子进程数组 {
		返回数组 = append(返回数组, int(子进程数组[i].Pid))
	}
	// 返回包含所有子进程ID的数组和nil错误，表示操作成功。
	return 返回数组, nil
}

type X进程文件信息 struct {
	X路径  string `json:"path"`
	X描述符 uint64 `json:"fd"`
}

// X取进程已打开文件 根据给定的进程ID，返回该进程所有已打开文件的信息。
// 参数:
// pid - 进程ID。
// 返回值:
// []X进程文件信息 - 包含已打开文件信息的切片, win平台会返回 \\?\ 前缀路径, 这是合法的,这是绕过短路径限制.
// error - 可能发生的错误，如果没有错误则返回nil。
func X取进程已打开文件(pid int) ([]X进程文件信息, error) {
	// 尝试获取指定ID的进程对象。
	p, err := process.NewProcess(int32(pid))
	if err != nil {
		// 如果无法获取进程对象，记录错误并返回空切片与错误信息。
		log.Printf("X取进程已打开文件(),打开进程失败:" + err.Error())
		return []X进程文件信息{}, err
	}
	// 获取进程所有已打开文件的信息。
	已打开文件, err := p.OpenFiles()
	if err != nil {
		// 如果获取已打开文件信息失败，记录错误并返回空切片与错误信息。
		log.Printf("X取进程已打开文件(),获取失败:" + err.Error())
		return []X进程文件信息{}, err
	}
	// 初始化用于存储已打开文件信息的切片。
	返回数组 := []X进程文件信息{}

	// 遍历已打开文件信息，并将其添加到返回的切片中。
	for i := range 已打开文件 {
		返回数组 = append(返回数组, X进程文件信息{
			X路径:  已打开文件[i].Path,
			X描述符: 已打开文件[i].Fd,
		})
	}
	// 返回已打开文件信息的切片，如果没有错误则返回nil。
	return 返回数组, nil
}

// X取进程用户名 根据给定的进程ID获取进程的用户名。
// 参数:
// pid - 进程ID。
// 返回值:
// 进程的用户名和一个可能的错误。
func X取进程用户名(pid int) (string, error) {
	// 尝试创建一个新的Process对象。
	p, err := process.NewProcess(int32(pid))
	if err != nil {
		// 如果创建Process对象失败，则返回错误信息。
		log.Printf("X取进程用户名(),打开进程失败:" + err.Error())
		return "", err
	}
	// 返回进程的用户名。
	return p.Username()
}

// X取进程环境变量 根据给定的进程ID获取进程的环境变量。
// 参数:
// pid - 进程ID。
// 返回值:
// []string - 进程的环境变量列表。
// error - 可能发生的错误。
func X取进程环境变量(pid int) ([]string, error) {
	// 尝试创建一个新的Process对象。
	p, err := process.NewProcess(int32(pid))
	if err != nil {
		// 如果创建Process对象失败，则返回错误信息。
		log.Printf("X取进程环境变量(),打开进程失败:" + err.Error())
		return []string{}, err
	}
	// 返回进程的环境变量列表。
	return p.Environ()
}
